﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

namespace LinqToOwin.Web.Labs.Data
{
  internal sealed class Weather
  {
    public string City
    {
      get;
      private set;
    }

    public string State
    {
      get;
      private set;
    }

    public decimal Latitude
    {
      get;
      private set;
    }

    public decimal Longitude
    {
      get;
      private set;
    }

    public ICollection<Uri> ConditionIcons
    {
      get;
      private set;
    }

    public int? MinimumTemperature
    {
      get;
      private set;
    }

    public int? MaximumTemperature
    {
      get;
      private set;
    }

    private Weather(string city, string state, decimal latitude, decimal longitude, IEnumerable<Uri> conditionIcons, int? minimumTemperature, int? maximumTemperature)
    {
      City = city;
      State = state;
      Latitude = latitude;
      Longitude = longitude;
      ConditionIcons = conditionIcons.ToList();
      MinimumTemperature = minimumTemperature;
      MaximumTemperature = maximumTemperature;
    }

    internal static IEnumerable<Weather> Parse(string xml, IEnumerable<string> cities, IDictionary<string, Tuple<decimal, decimal>> cityGrid)
    {
      var document = XDocument.Parse(xml);
      var data = document.Root.Element("data");

      return from location in data.Elements("location")
             let key = (string)location.Element("location-key")
             let cityElement = location.Element("city")
             let city = (string)cityElement
             let state = (string)cityElement.Attribute("state")
             where cities.Any(c => (city).IndexOf(c, StringComparison.OrdinalIgnoreCase) > -1)
             join parameters in data.Elements("parameters")
             on key equals (string)parameters.Attribute("applicable-location")
             let grid = cityGrid[WeatherClient.GetKey(city, state)]
             let icons = parameters.Element("conditions-icon")
             let iconLinks = icons == null ? null : icons.Elements("icon-link")
             select new Weather(
               city,
               state,
               grid.Item1,
               grid.Item2,
               from link in iconLinks ?? Enumerable.Empty<XElement>()
               let value = link.Value
               where !string.IsNullOrWhiteSpace(value)
               select new Uri(value, UriKind.Absolute),
               (from temperature in parameters.Elements("temperature")
                where (string)temperature.Attribute("type") == "minimum"
                select (int?)temperature.Element("value"))
               .FirstOrDefault(),
               (from temperature in parameters.Elements("temperature")
                where (string)temperature.Attribute("type") == "maximum"
                select (int?)temperature.Element("value"))
               .FirstOrDefault());
    }
  }
}